using System;
using System.Collections.Generic;
using System.Text;

namespace Acms.Bll
{
    public class UserPrinciple : System.Security.Principal.IPrincipal
    {
        private UserPrinciple(UserIdentity identity, Guid key, int siteId)
        {
            this.identity = identity;
            this.key = key;
            this.siteId = siteId;
        }

        private UserPrinciple()
        {
            this.identity = new UserIdentity(null);
        }

        public static UserPrinciple Construct(Guid key, int siteId)
        {
            User tmp = User.GetFromLoginKey(key);
            if(tmp != null)
            {
                return new UserPrinciple(new UserIdentity(tmp), key, siteId);
            }
            else
            {
                return new UserPrinciple();
            }
        }

        public static UserPrinciple Construct()
        {
            return new UserPrinciple();
        }

        private Guid key;
    
        private UserIdentity identity;
        public UserIdentity Identity
        {
	        get { return identity; }
        }

        private int siteId;
        public int SiteId
        {
            get { return siteId; }
        }

        List<UserRole> roles = null;
        private void EnsureRolesLoaded()
        {
            if (roles == null && this.Identity != null && this.Identity.User != null)
            {
                roles = this.Identity.User.GetCurrentRoles(siteId);
            }
        }

        public bool HasAdminRights()
        {
            EnsureRolesLoaded();
            if (roles != null)
            {
                foreach (UserRole r in roles)
                {
                    if (r.IsAdminRole)
                        return true;
                }
            }
            return false;
        }

        public bool HasRole(Acms.Bll.Role.Roles[] roles)
        {
            foreach (Acms.Bll.Role.Roles r in roles)
            {
                if(HasRole(r))
                {
                    return true;
                }
            }
            return false;
        }

        public bool HasRole(Acms.Bll.Role.Roles role)
        {
            if (this.Identity == null || this.Identity.User == null)
            {
                return role == Role.Roles.Anonomous;
            }
            else if(role == Role.Roles.Registered)
            {
                return true;
            }
            else
            {
                EnsureRolesLoaded();
                if (roles != null)
                {
                    foreach (UserRole r in roles)
                    {
                        if(r.IsRole(role))
                        {
                            return true;
                        }
                    }
                }
                return false;
            }
        }

        public bool IsInRole(string role)
        {
            if(string.IsNullOrEmpty(role))
                return false;

            if (role.ToLower() == "administrator")
            {
                return HasAdminRights();
            }
            else
            {
                EnsureRolesLoaded();

                if (roles != null)
                {
                    foreach (UserRole r in roles)
                    {
                        if (r.RoleName.ToLower() == role.ToLower())
                            return true;
                    }
                }
                return false;
            }
        }

        #region IPrincipal Members

        System.Security.Principal.IIdentity System.Security.Principal.IPrincipal.Identity
        {
            get { return this.Identity; }
        }

        bool System.Security.Principal.IPrincipal.IsInRole(string role)
        {
            return this.IsInRole(role);
        }

        public void Logout()
        {
            Identity.User.DeleteLoginKey(key);
            System.Web.Security.FormsAuthentication.SignOut();
        }
        #endregion
    }

    public class UserIdentity : System.Security.Principal.IIdentity
    {
        public UserIdentity(User user)
        {
            if(user != null && !user.IsNewRecord)
            {
                this.user = user;
            }
        }

        private User user;
        public User User
        {
            get { return user; }
        }
        
        public string  AuthenticationType
        {
	        get { return "Forms"; }
        }

        public bool  IsAuthenticated
        {
	        get { return user != null; }
        }

        public string  Name
        {
	        get 
            {
                return user == null ? null : user.UserName;
            }
        }


        public void RefreshUser()
        {
            user = User.GetById(user.Id);
        }

    }
}
